package com.member.shop.service.impl;

import com.alipay.api.AlipayApiException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.binarywang.wxpay.bean.order.WxPayAppOrderResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.member.common.enums.EnableStatusEnum;
import com.member.common.enums.OrderTypeEnum;
import com.member.common.exception.ServiceException;
import com.member.common.utils.DateUtils;
import com.member.common.utils.OrderNoCreate;
import com.member.common.utils.StringUtils;
import com.member.shop.domain.SysBizRecharge;
import com.member.shop.domain.SysBizRechargeUser;
import com.member.shop.domain.SysBizUser;
import com.member.shop.dto.RechargeSurplusDto;
import com.member.shop.dto.RechargeSurplusPayDto;
import com.member.shop.dto.WxPayDto;
import com.member.shop.mapper.SysBizRechargeMapper;
import com.member.shop.service.*;
import com.member.shop.vo.RechargePackageVo;
import com.member.shop.vo.RechargePayVo;
import com.member.shop.vo.SurplusVo;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RDelayedQueue;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 充值配置Service业务层处理
 *
 * @author lixinchen
 * @date 2024-05-08
 */
@Slf4j
@Service
public class SysBizRechargeServiceImpl extends ServiceImpl<SysBizRechargeMapper, SysBizRecharge> implements ISysBizRechargeService {
    @Resource
    private SysBizRechargeMapper sysBizRechargeMapper;
    @Resource
    private ISysBizUserService sysBizUserService;
    @Resource
    private ISysBizRechargeUserService sysBizRechargeUserService;
    @Resource
    private IPayService payService;
    @Resource
    private RDelayedQueue<String> delayedQueue;
    @Resource
    private IAlipayService alipayService;

    @Value("${alipay.notify-recharge-url}")
    private String aliPayNotifyUrl;

    /**
     * 查询充值配置
     *
     * @param id 充值配置主键
     * @return 充值配置
     */
    @Override
    public SysBizRecharge selectSysBizRechargeById(Long id) {
        return sysBizRechargeMapper.selectById(id);
    }

    /**
     * 查询充值配置列表
     *
     * @param queryWrapper 充值配置
     * @return 充值配置
     */
    @Override
    public List<SysBizRecharge> selectSysBizRechargeList(LambdaQueryWrapper<SysBizRecharge> queryWrapper) {
        return sysBizRechargeMapper.selectList(queryWrapper);
    }

    @Override
    public List<SysBizRecharge> selectSysBizRechargeList(SysBizRecharge sysBizRecharge) {
        return sysBizRechargeMapper.selectSysBizRechargeList(sysBizRecharge);
    }

    /**
     * 新增充值配置
     *
     * @param sysBizRecharge 充值配置
     * @return 结果
     */
    @Override
    public int insertSysBizRecharge(SysBizRecharge sysBizRecharge) {
        sysBizRecharge.setCreateTime(DateUtils.getNowDate());
        return sysBizRechargeMapper.insert(sysBizRecharge);
    }

    /**
     * 修改充值配置
     *
     * @param sysBizRecharge 充值配置
     * @return 结果
     */
    @Override
    public int updateSysBizRecharge(SysBizRecharge sysBizRecharge) {
        sysBizRecharge.setUpdateTime(DateUtils.getNowDate());
        return sysBizRechargeMapper.updateById(sysBizRecharge);
    }

    /**
     * 批量删除充值配置
     *
     * @param ids 需要删除的充值配置主键
     * @return 结果
     */
    @Override
    public int deleteSysBizRechargeByIds(Long[] ids) {
        return sysBizRechargeMapper.deleteBatchIds(Arrays.asList(ids));
    }

    /**
     * 删除充值配置信息
     *
     * @param id 充值配置主键
     * @return 结果
     */
    @Override
    public int deleteSysBizRechargeById(Long id) {
        return sysBizRechargeMapper.deleteById(id);
    }

    @Override
    public SurplusVo querySurplus(Long userId, Long tenantId) {
        // 先查用户余额
        SysBizUser sysBizUser = sysBizUserService.selectSysBizUserById(userId);
        SurplusVo surplusVo = new SurplusVo();
        surplusVo.setSurplus(sysBizUser.getSurplus());
        // 查询套餐
        LambdaQueryWrapper<SysBizRecharge> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysBizRecharge::getTenantId, tenantId);
        queryWrapper.eq(SysBizRecharge::getDisplayed, EnableStatusEnum.ENABLE.getKey());
//        queryWrapper.orderByDesc(SysBizRecharge::getOrderNum);
//        queryWrapper.orderByDesc(SysBizRecharge::getId);
        queryWrapper.orderByAsc(SysBizRecharge::getRechargePrice);
        List<SysBizRecharge> sysBizRecharges = sysBizRechargeMapper.selectList(queryWrapper);
        if (!CollectionUtils.isEmpty(sysBizRecharges)) {
            List<RechargePackageVo> rechargePackageVoList = new ArrayList<>();
            sysBizRecharges.forEach(sysBizRecharge -> {
                RechargePackageVo rechargePackageVo = new RechargePackageVo();
                rechargePackageVo.setId(sysBizRecharge.getId());
                rechargePackageVo.setCouponId(sysBizRecharge.getCouponId());
                rechargePackageVo.setGivePrice(sysBizRecharge.getGivePrice());
                rechargePackageVo.setGiveType(sysBizRecharge.getGiveType());
                rechargePackageVo.setCoupon(sysBizRecharge.getCoupon());
                rechargePackageVo.setRechargePrice(sysBizRecharge.getRechargePrice());
                rechargePackageVo.setPrice(sysBizRecharge.getRechargePrice().add(sysBizRecharge.getGivePrice()));
                rechargePackageVoList.add(rechargePackageVo);
            });
            surplusVo.setRechargePackageVoList(rechargePackageVoList);
        }
        return surplusVo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public SysBizRechargeUser rechargeSurplus(RechargeSurplusDto rechargeSurplusDto, Long userId) throws WxPayException {
        SysBizUser sysBizUser = sysBizUserService.selectSysBizUserById(userId);
        Date nowDate = DateUtils.getNowDate();
        // 先新增未付款订单
        SysBizRechargeUser sysBizRechargeUser = new SysBizRechargeUser();
        sysBizRechargeUser.setUserId(userId);
        sysBizRechargeUser.setAuditStatus(0);
        sysBizRechargeUser.setStatus(10);
        sysBizRechargeUser.setPaymentType(rechargeSurplusDto.getPaymentType());
        sysBizRechargeUser.setTenantId(sysBizUser.getTenantId());
        String orderCode = OrderNoCreate.surplusOrderCode(OrderTypeEnum.SURPLUS.name());
        sysBizRechargeUser.setOrderId(orderCode);
        sysBizRechargeUser.setPaymentStatus(0);
        sysBizRechargeUser.setUserPhone(sysBizUser.getUserPhone());
        sysBizRechargeUser.setNickName(sysBizRechargeUser.getNickName());
        sysBizRechargeUser.setCreateTime(nowDate);
        sysBizRechargeUser.setRechargeSource(1);
        sysBizRechargeUser.setCreateBy(sysBizUser.getNickName());
        sysBizRechargeUser.setRechargeBalanceBefore(sysBizUser.getSurplus());
        String uniqueId = StringUtils.leftPad(userId.toString(), 8, "0") + nowDate.getTime();
        String payId = "PAY" + uniqueId;
        sysBizRechargeUser.setPaymentNo(payId);
        sysBizRechargeUser.setPayTime(nowDate);
        //BigDecimal price;
        //BigDecimal rechargePrice;
        if (rechargeSurplusDto.getRechargeId() != null) {
            SysBizRecharge sysBizRecharge = sysBizRechargeMapper.selectById(rechargeSurplusDto.getRechargeId());
            if (sysBizRecharge == null) {
                throw new ServiceException("充值套餐不存在");
            }
            sysBizRechargeUser.setGiveType(sysBizRecharge.getGiveType());
            sysBizRechargeUser.setCouponId(sysBizRecharge.getCouponId());
            sysBizRechargeUser.setRechargePrice(sysBizRecharge.getRechargePrice());
            sysBizRechargeUser.setRechargeId(rechargeSurplusDto.getRechargeId());
            sysBizRechargeUser.setGivePrice(sysBizRecharge.getGivePrice() == null ? BigDecimal.ZERO : sysBizRecharge.getGivePrice());
            sysBizRechargeUser.setRechargeBalanceAfter(sysBizUser.getSurplus().add(sysBizRecharge.getRechargePrice()));//.add(sysBizRecharge.getGivePrice())
            //price = sysBizRecharge.getRechargePrice().add(sysBizRecharge.getGivePrice());
            //rechargePrice = sysBizRecharge.getRechargePrice();
        } else {
            sysBizRechargeUser.setRechargePrice(rechargeSurplusDto.getRechargePrice());
            sysBizRechargeUser.setGivePrice(BigDecimal.ZERO);
            sysBizRechargeUser.setRechargeBalanceAfter(sysBizUser.getSurplus().add(rechargeSurplusDto.getRechargePrice()));
            //price = rechargeSurplusDto.getRechargePrice();
            //rechargePrice = rechargeSurplusDto.getRechargePrice();
        }
        sysBizRechargeUser.setPayTimeEnd(DateUtils.addMinutes(DateUtils.getNowDate(), 15));
        sysBizRechargeUserService.save(sysBizRechargeUser);
        // 将数据存入redisson队列
        String key = "RECHARGE_SURPLUS_" + payId;
        delayedQueue.offerAsync(key, 60 * 15, TimeUnit.SECONDS);
        return sysBizRechargeUser;
    }

    @Override
    public RechargePayVo paymentRecharge(RechargeSurplusPayDto rechargeSurplusPayDto) throws WxPayException {
        SysBizRechargeUser sysBizRechargeUser = sysBizRechargeUserService.selectSysBizRechargeUserById(rechargeSurplusPayDto.getId());
        RechargePayVo rechargePayVo = new RechargePayVo();
        // 判断支付类型
        if (rechargeSurplusPayDto.getPaymentType() == 0) {
            // 微信支付
            WxPayAppOrderResult wxPayMpOrderResult = payService.wxAppPay(WxPayDto.builder()
                    .payId(sysBizRechargeUser.getPaymentNo())
                    .orderId(sysBizRechargeUser.getOrderId())
                    .totalFee(sysBizRechargeUser.getRechargePrice())
                    .spbillCreateIp("127.0.0.1")
                    .tenantId(sysBizRechargeUser.getTenantId())
//                    .openId(sysBizUser.getOpenId())
                    .notifyUrl("/mp-api/wx/payment/callbackBySurplus")
                    .build());
            rechargePayVo.setWxPayMpOrderResult(wxPayMpOrderResult);
            return rechargePayVo;
        } else { // 支付宝支付
            try {
                String orderStr = alipayService.createOrderByNotifyUrl
                        (sysBizRechargeUser.getTenantId(),
                        sysBizRechargeUser.getPaymentNo(),
                        sysBizRechargeUser.getRechargePrice().doubleValue(),
                        sysBizRechargeUser.getOrderId(),
                        aliPayNotifyUrl);
                rechargePayVo.setAliPayResult(orderStr);
                log.info("zfb pay orderStr ----------------orderStr:{}",orderStr);
            } catch (AlipayApiException e) {
                throw new RuntimeException(e);
            }
            return rechargePayVo;
        }
    }

}
